/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package frontera.dao;

import control.SIRHApp;
import entidad.Bono;
import entidad.CambiosEmpleado;
import entidad.Empleado;
import entidad.Falla;
import entidad.HoraExtra;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author tuareg
 */
public class EmpleadoDAO  extends DAOT<Empleado>{

	public EmpleadoDAO(String nombreEntidad) {
		super(nombreEntidad);
	}

	public EmpleadoDAO() {
		this("Empleado");
	}
        
        @Override
        public boolean crear(Empleado nuevaEntidad) {
		boolean retorno = false;
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();

                CambiosEmpleado cambiosTMP = new CambiosEmpleado();
                cambiosTMP.getCambios().add(nuevaEntidad);
                nuevaEntidad.setCambiosEmpleado(cambiosTMP);
		nuevaEntidad.setUltimaVersion(true);
                SIRHApp.getInstance().getDAOCamEmpleado().crear(cambiosTMP);
                
                
		try {
                        em.persist(nuevaEntidad);
			em.getTransaction().commit();
			retorno = true;
		} catch (Exception e) {
			e.printStackTrace();
			em.getTransaction().rollback();
		} finally {
			em.close();
			return retorno;
		}
	}
                
	@Override
        public boolean actualizar(Empleado viejaEntidad, Empleado nuevaEntidad) {
            EntityManager em = emf.createEntityManager();
            em.getTransaction().begin();
            boolean ret= false;
            try {
                if(SIRHApp.getInstance().getAdmCambios().verificarFecha(viejaEntidad.getFechaDeModificacion(), 
                                                                        nuevaEntidad.getFechaDeModificacion())){
                    viejaEntidad = leer(viejaEntidad);
                    viejaEntidad.setNombre(nuevaEntidad.getNombre());
                    viejaEntidad.setCedula(nuevaEntidad.getCedula());
                    viejaEntidad.setTelefono(nuevaEntidad.getTelefono());
                    viejaEntidad.setDireccion(nuevaEntidad.getDireccion());
                    viejaEntidad.setProfesion(nuevaEntidad.getProfesion());
                    viejaEntidad.setEstado(nuevaEntidad.getEstado());
                    viejaEntidad.setPorcentajeSalarioBas(nuevaEntidad.getPorcentajeSalarioBas());
                    viejaEntidad.setCargoAsociado(nuevaEntidad.getCargoAsociado());
                    viejaEntidad.setEPS(nuevaEntidad.getEPS());
                    actualizarFallas(nuevaEntidad.getFallas(), viejaEntidad);
                    actualizarBonos(nuevaEntidad.getBonos(), viejaEntidad);
                    actualizarHorasExtras(nuevaEntidad.getHorasExtra(), viejaEntidad);
                    viejaEntidad.setFechaDeModificacion(nuevaEntidad.getFechaDeModificacion());
                    em.merge(viejaEntidad);
                    em.getTransaction().commit();
                    ret = true;
                }
                else{
                    try {
                            nuevaEntidad.setCambiosEmpleado(viejaEntidad.getCambiosEmpleado());
                            actualizarFallas(nuevaEntidad.getFallas(), nuevaEntidad);
                            actualizarBonos(nuevaEntidad.getBonos(), nuevaEntidad);
                            actualizarHorasExtras(nuevaEntidad.getHorasExtra(), nuevaEntidad);
			    nuevaEntidad.setUltimaVersion(true);
			    viejaEntidad.setUltimaVersion(false);
			    em.merge(viejaEntidad);
                            em.persist(nuevaEntidad);
                            em.getTransaction().commit();
                            ret = true;
                    } catch (Exception e) {
                            e.printStackTrace();
                            em.getTransaction().rollback();
                    }
                }
            } catch (Exception e) {
                em.getTransaction().rollback();
            } finally {
                em.close();
                return ret;
            }
        }
        
        public Empleado getEmpleadoID(long ID){
            EntityManager em = emf.createEntityManager();
            Empleado empleado = null;

            Query q = em.createQuery(   "SELECT e FROM Empleado e " +
                                        "WHERE e.ID = :ID")
                                        .setParameter("ID",ID);
            try {                       
                empleado = (Empleado)q.getSingleResult();
            } catch (NonUniqueResultException e) {
                empleado = (Empleado)q.getResultList().get(0);
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                em.close();
                return empleado;
            }
        }
        
        public Empleado leer(Empleado par) {
            EntityManager em = emf.createEntityManager();
            Empleado empleado = null;

            Query q = em.createQuery(   "SELECT e FROM Empleado e " +
                                        "WHERE e.cedula = :CEDULA AND "
                                        + "e.fechaDeModificacion = :FECHA")
                                        .setParameter("CEDULA",par.getCedula())
                                        .setParameter("FECHA", par.getFechaDeModificacion());
            try {                       
                empleado = (Empleado)q.getSingleResult();
            } catch (NonUniqueResultException e) {
                empleado = (Empleado)q.getResultList().get(0);
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                em.close();
                return empleado;
            }
        }
        
        public ArrayList<Empleado> getCambiosID(long ID,Calendar fecha){
            EntityManager em = emf.createEntityManager();
            ArrayList<Empleado> cambios = null;
            
            Query q = em.createQuery(   "SELECT e FROM Empleado e " +
                                        "WHERE e.cambiosEmpleado.id = :CAMBIOSEMPLEADO_ID AND "
                                        + "e.fechaDeModificacion <= :FECHA")
                                        .setParameter("CAMBIOSEMPLEADO_ID",ID)
                                        .setParameter("FECHA", fecha);
            try {                       
                cambios = (ArrayList<Empleado>) q.getResultList();
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                em.close();
                return cambios;
            }
        }
        
        public ArrayList<Empleado> getEmpleadosCargo(Long id){
            EntityManager em = emf.createEntityManager();
            ArrayList<Empleado> empleados = null;
            
            Query q = em.createQuery("SELECT e FROM Empleado e "+
                                     "WHERE e.cargoAsociado.idCargo = :CARGOASOCIADO_IDCARGO")
                                     .setParameter("CARGOASOCIADO_IDCARGO", id);
            try{
                empleados = (ArrayList<Empleado>) q.getResultList();
            }catch (Exception e){
                e.printStackTrace();
            }finally{
                em.close();
                return empleados;
            }
        }
        
        public Empleado getMinimaFecha(){
            EntityManager em = emf.createEntityManager();
            Empleado cambios = null;
            
            Query q = em.createQuery(   "SELECT p FROM Empleado p "+
                                        "WHERE p.fechaDeModificacion=(SELECT MIN(p.fechaDeModificacion) FROM p)");
            try {                       
                cambios = (Empleado) q.getSingleResult();
            } catch (NonUniqueResultException e) {
                cambios = (Empleado)q.getResultList().get(0);
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                em.close();
                return cambios;
            }
        }       

        public void actualizarFallas(List<Falla> fallasTemporales, Empleado empleado){
            
            long ID = empleado.getID();
            List<Falla> copiaFallas = fallasTemporales;
            List<Falla> copiaFallasBD = SIRHApp.getInstance().getDAOFalla().leerListado(ID);

            for (Falla fa : copiaFallas)
            {
                Falla fallaBuscada = SIRHApp.getInstance().getDAOFalla().leer(fa);
                
                if (fallaBuscada == null){
                    SIRHApp.getInstance().getDAOFalla().crear(fa);
                }
                        
                else {
                    copiaFallasBD.remove(buscarFalla(copiaFallasBD, fallaBuscada.getId()));
                }
            }
            
            for (Falla fa : copiaFallasBD){
                SIRHApp.getInstance().getDAOFalla().eliminar(fa);
            }    
            
            empleado.setFallas(copiaFallas);

        }
        
         private void actualizarBonos(List<Bono> bonosTemporales, Empleado empleado){
            
            long ID = empleado.getID();
            List<Bono> copiaBonos = bonosTemporales;
            List<Bono> copiaBonosBD = SIRHApp.getInstance().getDAOBono().leerListado(ID);

            for (Bono bo : copiaBonos)
            {
                Bono bonoBuscado = SIRHApp.getInstance().getDAOBono().leer(bo);
                
                if (bonoBuscado == null){
                    SIRHApp.getInstance().getDAOBono().crear(bo);
                }
                        
                else {
                    copiaBonosBD.remove(buscarBono(copiaBonosBD, bonoBuscado.getId()));
                }
            }
            
            for (Bono bo : copiaBonosBD){
                SIRHApp.getInstance().getDAOBono().eliminar(bo);
            }              
        }
        
        private void actualizarHorasExtras(List<HoraExtra> horasExtrasTemporales, Empleado empleado){
            
            long ID = empleado.getID();  
            List<HoraExtra> copiaHorasExtras = horasExtrasTemporales;
            List<HoraExtra> copiaHorasExtrasBD = SIRHApp.getInstance().getDAOHoraExtra().leerListado(ID);

            for (HoraExtra he : copiaHorasExtras)
            {
                HoraExtra horaBuscada = SIRHApp.getInstance().getDAOHoraExtra().leer(he);
                
                if (horaBuscada == null){
                    SIRHApp.getInstance().getDAOHoraExtra().crear(he);
                }
                        
                else {
                    copiaHorasExtrasBD.remove(buscarHoraExtra(copiaHorasExtrasBD, horaBuscada.getId()));
                }
            }
            
            for (HoraExtra he : copiaHorasExtrasBD){
                SIRHApp.getInstance().getDAOHoraExtra().eliminar(he);
            }              
        }

        private Falla buscarFalla(List<Falla> fallas, long ID){
            for(Falla fa: fallas){
                if(fa.getId()==ID){
                    return fa;
                }
            }
            return null;
        }
        
        private Bono buscarBono(List<Bono> bonos, long ID){
            for(Bono bo: bonos){
                if(bo.getId() == ID){
                    return bo;
                }
            }
            return null;
        }
        
        private HoraExtra buscarHoraExtra(List<HoraExtra> horasExtras, long ID){
            for(HoraExtra he: horasExtras){
                if(he.getId() == ID){
                    return he;
                }
            }
            return null;
        }   
        
}
